package com.shuyihui.identity

import com.shuyihui.identity.bean.Spec
import com.shuyihui.identity.bean.SpecCombination

/**
 * 创建日期 2022/3/10
 * 描述：
 */
object SpecSkuUtil {
    /**
     * 获取类型index
     */
    private fun getTypeIndex(column: Int, specTypeCount: List<Int>): Int {
        var c = 0
        var typeIndex = 0
        for (index in specTypeCount.indices) {
            c += specTypeCount[index]
            if (column < c) {
                typeIndex = index
                break
            }
        }
        return typeIndex
    }

    /**
     * 已选中某个规格后的可供选择规则
     * 选中"紫色"，返回["1","2","3"]
     * 选中"套餐一"，返回["1","2"]
     */
    private fun getMatchIdList(typeIndex: Int, specName: String, specCombinationList: List<SpecCombination>): List<String> {
        return specCombinationList
            .filter { combination -> specName == combination.specs[typeIndex] }
            .map { it.id }
    }

    private fun getCombinations(specCombinationList: List<SpecCombination>, matchIds: List<String>? = null): Array<MutableList<String>> {
        val size = if (specCombinationList.isNullOrEmpty()) 0 else specCombinationList.first().specs.size
        val cs = Array<MutableList<String>>(size) { mutableListOf() }
        specCombinationList.forEach {
            if (matchIds == null || matchIds.contains(it.id)) {
                it.specs.forEachIndexed { index, spec ->
                    cs[index].add(spec)
                }
            }
        }
        return cs
    }

    fun transformMatrix(specList: List<Spec>, specCombinationList: List<SpecCombination>): Array<IntArray> {
        var num = 0 // 记录邻接矩阵的大小
        val specs = mutableListOf<String>() // 记录所有规格
        val specTypeCount = mutableListOf<Int>() // 记录每个类别的数目
        specList.forEach {
            specs.addAll(it.list)
            specTypeCount.add(it.list.size)
            num += it.list.size
        }
        val combinations = getCombinations(specCombinationList)

        // 二维数组
        val matrix = Array(num) { IntArray(num) }

        // 遍历(n*n-n)/2次
        for (row in 0 until num) {
            val rowTypeIndex = getTypeIndex(row, specTypeCount)
            if (!combinations[rowTypeIndex].contains(specs[row])) {
                continue
            }
            for (column in 0 until row) {
                val columnTypeIndex = getTypeIndex(column, specTypeCount)
                if (!combinations[columnTypeIndex].contains(specs[column])) {
                    continue
                }
                val isEqualsType = rowTypeIndex == columnTypeIndex
                val matchIdList = if (!isEqualsType) {
                    getMatchIdList(rowTypeIndex, specs[row], specCombinationList)
                } else emptyList()

                if (isEqualsType) {
                    // 同一类别规格不同就为1（横向为"红"，纵向只要specCombinationList包含紫色就为1）
                    if (specs[row] != specs[column]) {
                        matrix[row][column] = 1
                        matrix[column][row] = 1 // 对称
                    }
                } else {
                    // 不同类别规格相同就为1
                    val newCombinations = getCombinations(specCombinationList, matchIdList)
                    if (newCombinations[columnTypeIndex].contains(specs[column])) {
                        matrix[row][column] = 1
                        matrix[column][row] = 1 // 对称
                    }
                }
            }
        }
        return matrix
    }

    /**
     * 默认可选择
     */
    fun allOr(matrix: Array<IntArray>): IntArray {
        val m = IntArray(matrix.size) { 0 }
        for (row in matrix.indices) {
            for (column in matrix.indices) {
                m[column] = m[column].or(matrix[row][column])
            }
        }
        return m
    }

    fun rowAnd(rows: ArrayList<Int>, matrix: Array<IntArray>): IntArray {
        val m = allOr(matrix)
        for (row in rows) {
            for (column in matrix.indices) {
                m[column] = m[column].and(matrix[row][column])
            }
        }
        return m
    }

    /**
     * 可选的规格
     */
    fun getCanSelectSpec(m: IntArray, specList: List<Spec>): MutableList<IntArray> {
        val canSelectSpecs = mutableListOf<IntArray>()
        var start = 0
        specList.forEach {
            val end = start + it.list.size
            canSelectSpecs.add(m.sliceArray(start until end))
            start = end
        }
        return canSelectSpecs
    }
}